package org.price.sql.repo.session.core;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.log4j.Logger;
import org.price.sql.repo.documents.config.Document;
import org.price.sql.repo.documents.config.Documents;
import org.price.sql.repo.exceptions.SessionException;
import org.price.sql.repo.session.Session;
import org.price.sql.repo.session.SessionFactory;
import org.price.sql.repo.session.db.dialect.Dialect;

@SuppressWarnings("unchecked")
public class SessionFactoryImpl implements SessionFactory {

    private static final Logger LOG = Logger.getLogger(SessionFactoryImpl.class);

    protected Dialect dialect;

    protected Connection connection;

    protected Unmarshaller unmarshaller;

    protected Map<String, DocumentInfo> docs;

    public SessionFactoryImpl(Connection connection) {
        this.connection = connection;
    }

    public Map<String, DocumentInfo> getDocs() {
        if (docs == null) {
            docs = new Hashtable<String, DocumentInfo>();
        }

        return docs;
    }

    public Session createSession() throws SessionException {
        return null;
    }

    public Dialect getCurrentDialect() throws SQLException {
        try {
            if (dialect == null) {

                DialectDetector dd = (DialectDetector) Class.forName(
                        Core.getProperties().get(Core.DIALECT_DETECTOR).toString()).newInstance();

                dialect = dd.getDialect(connection);
            }
        } catch (Exception e) {
            throw new SQLException(e.getLocalizedMessage());
        }

        return dialect;
    }

    public Unmarshaller getUnmarshaller() throws JAXBException {
        if (unmarshaller == null) {
            JAXBContext context = JAXBContext.newInstance("org.price.sql.repo.documents.config");
            unmarshaller = context.createUnmarshaller();
        }

        return unmarshaller;
    }

    public void addDocumentType(File file) throws IOException, JAXBException {
        addDocumentType(new FileInputStream(file));
    }

    public void addDocumentType(InputStream stream) throws JAXBException {
        Object elem = getUnmarshaller().unmarshal(stream);

        Documents docs = elem instanceof Documents ? (Documents) elem
                : ((JAXBElement<Documents>) elem).getValue();
        LOG.info(docs);

        for (Document doc : docs.getDocument()) {
            createBackEnd(doc);
        }
    }

    private void createBackEnd(Document doc) {

    }

    public void addDocumentType(String string) throws JAXBException {
        addDocumentType(new ByteArrayInputStream(string.getBytes()));
    }

    public void rebuildBackbase() throws SQLException {
        DocumentInfo[] dInfos = (DocumentInfo[]) getCurrentDialect().getTables();
    }

}
